home *** CD-ROM | disk | FTP | other *** search
/ Informática Multimedia 1995 April / Informatica Multimedia CD - Epimundo.iso / DOS / FILEFIND / FFF.ZIP / FFF.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-09  |  21.5 KB  |  698 lines

  1. /*---------------------------------------------------------------------------*/
  2. /*      FFF.COM - Fast-File-Find, a fully public domain program to search
  3.  *                  for files on one or more disks (functionally similar to
  4.  *                the familiar "WHERE" program.  FFF will also search inside
  5.  *                of ZIP, ARC, PKA, and ZOO archives to the first level.
  6.  *
  7.  *      Version:  3.4.5
  8.  *      Date:     July 9, 1990
  9.  *      Author:   Don A. Williams
  10.  *
  11.             *********************  NOTICE  ************************
  12.             *  Contrary to the current trend in MS-DOS  software  *
  13.             *  this  program,  for whatever it is worth,  is NOT  *
  14.             *  copyrighted (with the exception  of  the  runtime  *
  15.             *  library  from  the C compiler)!  The program,  in  *
  16.             *  whole or in part,  may  be  used  freely  in  any  *
  17.             *  fashion or environment desired.  If you find this  *
  18.             *  program  to  be  useful  to you,  do NOT send any  *
  19.             *  contribution to the author;  in the words of Rick  *
  20.             *  Conn,   'Enjoy!'   However,   if   you  make  any  *
  21.             *  improvements,  I would enjoy receiving a copy  of  *
  22.             *  the  modified source.  I can be reached,  usually  *
  23.             *  within 24  hours,  by  messages  on  any  of  the  *
  24.             *  following Phoenix, AZ systems (the Phoenix systems *
  25.             *  can all be reached through StarLink node #9532):   *
  26.             *                                                     *
  27.             *     The Tool Shop BBS       [PCBOARD] [PC-Pursuit]  *
  28.             *         (602) 279-2673   1200/2400/9600 bps         *
  29.             *     Technoids Anonymous     [PCBOARD]               *
  30.             *         (602) 899-4876   300/1200/2400 bps          *
  31.             *         (602) 899-5233                              *
  32.             *         (602) 786-9131                              *
  33.             *     Inn On The Park         [PCBOARD]               *
  34.             *         (602) 957-0631   1200/2400/9600 bps         *
  35.             *     Pascalaholics Anonymous [WBBS]                  *
  36.             *         (602) 484-9356   1200/2400 bps              *
  37.             *                                                     *
  38.             *  or:                                                *
  39.             *     Blue Ridge Express     [RBBS] Richmond, VA      *
  40.             *         (804) 790-1675   2400 bps [StarLink #413]   *
  41.             *                                                     *
  42.             *     The Lunacy BBS         [PCBOARD] Van Nuys, CA   *
  43.             *         (805) 251-7052   2400/9600 [StarLink 6295]  *
  44.             *         (805) 251-8637   2400/9600 [StarLink 6295]  *
  45.             *                                                     *
  46.             *  or:                                                *
  47.             *     GEnie, mail address: DON-WILL                   *
  48.             *     CompuServ:           75410,543                  *
  49.             *                                                     *
  50.             *  Every  effort  has  been  made to avoid error and  *
  51.             *  moderately extensive testing has  been  performed  *
  52.             *  on  this  program,  however,  the author does not  *
  53.             *  warrant it to be fit for any  purpose  or  to  be  *
  54.             *  free  from  error and disclaims any liability for  *
  55.             *  actual or any other damage arising from  the  use  *
  56.             *  of this program.                                   *
  57.             *******************************************************
  58. */
  59.  
  60. #include <stdio.h>
  61. #include <stdlib.h>
  62. #include <string.h>
  63. #include <ctype.h>
  64. #include <dos.h>
  65. #ifdef __TURBOC__
  66.     #include <dir.h>
  67.     #include <conio.h>
  68. #endif
  69. #include <stddef.h>
  70. #include <stdarg.h>
  71. #include <io.h>
  72. #include <conio.h>
  73.  
  74. #define MAIN
  75.  
  76. #define VERSION "Version 3.4.5"
  77. #define VER_DATE "July 9, 1990"
  78.  
  79. /*------------------------------------------------------------------*/
  80. /*  Turbo C and Microsoft C have different names for the structure    */
  81. /*  that defines an MS DOS directory entry, different names for    the    */
  82. /*  elements of that structure, different names for the attribute    */
  83. /*  masks, and a slightly different parameter sequence for the        */
  84. /*  "FindFirst/FindNext" functions.                                    */
  85.  
  86. #ifdef __TURBOC__
  87.     #define FIND_FIRST(Name,Block,Attrib) findfirst(Name, Block, Attrib)
  88.     #define FIND_NEXT(Block) findnext(Block)
  89.  
  90.     #define DIR_ENTRY ffblk        /* Name of the directory entry structure    */
  91.     #define D_ATTRIB ff_attrib    /* Attribute filed in directory entry        */
  92.     #define D_TIME ff_ftime        /* Time field in directory entry            */
  93.     #define D_DATE ff_fdate        /* Date field in directory entry            */
  94.     #define D_SIZE ff_fsize        /* File size field in directory entry        */
  95.     #define D_NAME ff_name        /* File name field in directory entry        */
  96.  
  97.     #define A_RDONLY FA_RDONLY    /* Read only attribute mask                    */
  98.     #define A_HIDDEN FA_HIDDEN    /* Hidden attribute mask                    */
  99.     #define A_SYSTEM FA_SYSTEM    /* System attribute mask                    */
  100.     #define A_VOLID FA_LABEL    /* Volume Label attribute mask                */
  101.     #define A_DIREC FA_DIREC    /* Subdirectory attribute mask                */
  102.     #define A_ARCH FA_ARCH        /* Archived attribute mask                    */
  103. #else
  104.     #define FIND_FIRST(Name,Block,Attrib) _dos_findfirst(Name, Attrib, Block);
  105.     #define FIND_NEXT(Block) _dos_findnext(Block);
  106.  
  107.     #define DIR_ENTRY find_t    /* Name of the directory entry structure    */
  108.     #define D_ATTRIB attrib        /* Attribute filed in directory entry        */
  109.     #define D_TIME wr_time         /* Time field in directory entry            */
  110.     #define D_DATE wr_date         /* Date field in directory entry            */
  111.     #define D_SIZE size            /* File size field in directory entry        */
  112.     #define D_NAME name           /* File name field in directory entry        */
  113.  
  114.     #define A_RDONLY _A_RDONLY    /* Read only attribute mask                    */
  115.     #define A_HIDDEN _A_HIDDEN    /* Hidden attribute mask                    */
  116.     #define A_SYSTEM _A_SYSTEM    /* System attribute mask                    */
  117.     #define A_VOLID _A_VOLID    /* Volume Label attribute mask                */
  118.     #define A_DIREC _A_SUBDIR    /* Subdirectory attribute mask                */
  119.     #define A_ARCH _A_ARCH        /* Archived attribute mask                    */
  120. #endif
  121.  
  122. #include "fff.h"
  123. #include "queue.h"
  124. #include "arc.h"
  125. #include "zip.h"
  126. #include "zoo.h"
  127. #include "lzh.h"
  128.  
  129. #ifdef PROF                        /* Instrumentation                            */
  130.     #include "pchrt.h"
  131. #endif
  132.  
  133. void            WalkTree (QUE_DEF * Q);
  134. int             SearchQ (char *Str);
  135. int             Match (char *Str, char *Pat);
  136. void            PrtVerbose (char *Path, char *Name, DOS_FILE_TIME * Time,
  137.                            DOS_FILE_DATE * Date, long Size);
  138. void            Usage (void);
  139. void            ChkPage (void);
  140.  
  141. void            GetCurrentDisk (int *CurDisk);
  142. int             GetCurrentDirectory (int Disk, char *CurDir);
  143. void            ErrorExit (char *Format,...);
  144. void            GetProgName (char *Name, char *argv);
  145.  
  146. /*----------------------------------------------------------------------*/
  147. /*  Microsoft C 5.1 does not provide the following function which is    */
  148. /*  provided by Turbo C 2.0                                                */
  149.  
  150. #ifndef __TURBOC__
  151.  
  152. void clreol (void);
  153.  
  154. #endif
  155. /*----------------------------------------------------------------------*/
  156.  
  157. char            Path[65];            /* Current directory path to search        */
  158. char            T_Path[65];            /* Temporary directory path to search    */
  159. char            Temp[66];            /* Temporary working storage            */
  160. char            V_Name[14];
  161. char             V_Path[66];
  162.  
  163. char            CurDir[67];            /* Full path of the current directory    */
  164. unsigned long   Position;
  165. char            ProgName[9];        /* File name of this program            */
  166.  
  167. int             Spaced = 0;            /* Indicates if blank line separator    */
  168. int             Lnno = 1;            /* Line count for paged output            */
  169. int             TotalFiles = 0;        /* Total files processed                */
  170. int             TotalMatch = 0;        /* Count of all files matched            */
  171.  
  172. ARC_TYPE        ArcType;
  173.  
  174. struct Archives {                    /* Structure to identify archive files    */
  175.     char            Ext[4];            /* processed by Extent                    */
  176.     ARC_TYPE        Type;
  177.     }               Arcs[6] = {
  178.         {"ARC", arc},
  179.         {"LZH", lzh},
  180.         {"PAK", arc},
  181.         {"ZIP", zip},
  182.         {"ZOO", zoo},
  183.         {"", none}
  184.         };
  185.  
  186. int             S[6][3] = {
  187.     {0, 0, 0},                    /* Dummy          */
  188.     {0, 0, 0},                    /* Arc File Stats */
  189.     {0, 0, 0},                    /* Zip File Stats */
  190.     {0, 0, 0},                    /* Zoo File Stats */
  191.     {0, 0, 0},                    /* Pak File Stats */
  192.     {0, 0, 0}                    /* Lzh File Stats */
  193.     };
  194.  
  195. /*---  Option Switches  --- */
  196.  
  197. int             ArcSwt = 1;        /* Search inside of archives - default ON    */
  198. int             PageSwt = 0;    /* Paginate output - default OFF            */
  199. int             VerboseSwt = 0;    /* Verbose out put - default OFF            */
  200. int             QuietSwt = 0;    /* Supress stats   - default OFF            */
  201. int             DateSwt = 0;    /* International date formaat - default OFF    */
  202. int                UsDateSwt = 0;    /* US date format - defualt OFF                */
  203. int                CaseSwt = 0;    /* Output in lower case -default OFF        */
  204.  
  205. /*---  End Option Switches  --- */
  206.  
  207.  
  208. char           *Legend[] = {
  209.     "NONE", "ARC", "ZIP", "ZOO", "PAK", "LZH", ""
  210.     };
  211.  
  212. char            Devices[16] = "";
  213.  
  214. QUE_DEF         PatQue;
  215.  
  216.  void
  217. main (int argc, char *argv[]) {
  218.     int             CurDisk, i;
  219.     char           *p, *pe, *p2, *Temp;
  220.  
  221. /* The following conditional compilation sets up the PCHRT routines used    */
  222. /* for instrumentation.  You'll need the PCHRT package to use it.            */
  223.  
  224. #ifdef PROF
  225.     if ( t_start() == NULL) {
  226.         fprintf(stderr, "Oops!  No memory!\n");
  227.         exit(1);
  228.         }
  229.     t_name(0, "Total Program");
  230.     t_name(1, "WalkTree");
  231.     t_name(2, "FindFirst/Next");
  232.     t_name(3, "Match");
  233.     t_name(4, "ProcZip");
  234.     t_entry(0);
  235. #endif
  236.  
  237.     GetProgName(ProgName, argv[0]);
  238.     fprintf(stderr, "%s: FastFileFind - %s: %s\n", ProgName, VERSION, VER_DATE);
  239.     InitQueue(&PatQue);
  240.     GetCurrentDisk(&CurDisk);
  241.     CurDir[0] = (char) (CurDisk + 'A');
  242.     CurDir[1] = ':';
  243.     CurDir[2] = '\\';
  244.     GetCurrentDirectory(CurDisk, CurDir + 3);
  245.     strupr(CurDir);
  246.     strcpy(Path, "C:\\");
  247.     p = getenv("FFF");
  248.  
  249. /* Interpret the Environment Variable, if any                        */
  250.  
  251.     if (p != NULL) {
  252.         Temp = malloc(strlen(p) + 1);
  253.         strcpy(Temp, p);
  254.         p = Temp;
  255.         while ( (p != NULL) && (*p != '\0') ) {
  256.             pe = &p[strspn(p, " ")];
  257.             if (*pe == '\0') break;
  258.             p = pe;
  259.             if ((pe = strchr(p, ' ')) != NULL) *pe++ = '\0';
  260.             if (*p != '-') {
  261.                 if ((p2 = strchr(p, ':')) != NULL) *p2 = '\0';
  262.                 strcpy(Devices, p);
  263.                 p = pe;
  264.                 }
  265.             else {
  266.                 while (*++p != '\0') switch (tolower(*p)) {
  267.                     case 'a':
  268.                         ArcSwt ^= ON;
  269.                         break;
  270.                     case 'v':
  271.                         VerboseSwt ^= ON;
  272.                         break;
  273.                     case 'p':
  274.                         PageSwt ^= ON;
  275.                         break;
  276.                     case 'q':
  277.                         QuietSwt ^= ON;
  278.                         break;
  279.                     case 'f':
  280.                         DateSwt = ON;
  281.                         if (UsDateSwt) UsDateSwt = OFF;
  282.                         break;
  283.                     case 'u':
  284.                         UsDateSwt = ON;
  285.                         if (DateSwt) DateSwt = OFF;
  286.                         break;
  287.                     case 'c':
  288.                         CaseSwt ^= ON;
  289.                         break;
  290.                     default:
  291.                         fprintf(stderr, "Invalid option in Environment: %c\n", *p);
  292.                         fprintf(stderr, "    Ignored.\n");
  293.                         break;
  294.                     }
  295.                 }
  296.             }
  297.         free(Temp);
  298.         }
  299.  
  300. /* If no devices in Environment Variable, make default current disk    */
  301.  
  302.     if (Devices[0] == '\0') {
  303.         Devices[0] = (char) (CurDisk + 'A');
  304.         Devices[1] = '\0';
  305.         }
  306.  
  307. /* Interpret Command Line arguments                                    */
  308.  
  309.     if (argc < 2) Usage();
  310.     for (i = 1; i < argc; ++i) {
  311.         if (argv[i][0] == '-') {
  312.             for (p = &argv[i][1]; *p != '\0'; ++p) switch (tolower(*p)) {
  313.                 case 'a':
  314.                     ArcSwt ^= ON;
  315.                     break;
  316.                 case 'v':
  317.                     VerboseSwt ^= ON;
  318.                     break;
  319.                 case 'p':
  320.                     PageSwt ^= ON;
  321.                     break;
  322.                 case 'q':
  323.                     QuietSwt ^= ON;
  324.                     break;
  325.                 case 'f':
  326.                     DateSwt ^= ON;
  327.                     if (UsDateSwt) UsDateSwt = OFF;
  328.                     break;
  329.                 case 'u':
  330.                     UsDateSwt ^= ON;
  331.                     if (DateSwt) DateSwt = OFF;
  332.                     break;
  333.                 case 'c':
  334.                     CaseSwt ^= ON;
  335.                     break;
  336.                 default:
  337.                     fprintf(stderr, "Invalid argument: %c\n", argv[i][1]);
  338.                     Usage();
  339.                     break;
  340.                 }
  341.             }
  342.         else {
  343.             p = argv[i];
  344.             if ((p2 = strchr(p, ':')) != NULL) {
  345.                 *p2++ = '\0';
  346.                 strcpy(Devices, p);
  347.                 p = p2;
  348.                 Enque(&PatQue, strupr(p));
  349.                 }
  350.             else if ((p2 = strrchr(p, '\\')) != NULL) strcpy(Path, p);
  351.             else Enque(&PatQue, strupr(p));
  352.             }
  353.         }
  354.  
  355. /* This does the work by walking the directory structure for each specified    */
  356. /* disk                                                                        */
  357.  
  358.     p = Devices;
  359.     while (*p != '\0') {
  360.         strcpy(T_Path, Path);
  361.         T_Path[0] = *p++;
  362. #ifdef PROF
  363.         t_entry(1);
  364. #endif
  365.         WalkTree(&PatQue);
  366. #ifdef PROF
  367.         t_exit(1);
  368. #endif
  369.         }
  370.  
  371. /* Display statistics                                            */
  372.  
  373.     if (!QuietSwt) {
  374.         if (PageSwt) ChkPage();
  375.         if (!Spaced) printf("\n");
  376.         printf("Total Files = %6d  Total Matched Files = %d\n", TotalFiles, TotalMatch);
  377.         for (i = 0; Legend[i][0] != '\0'; ++i) {
  378.             if (S[i][0] != 0) {
  379.                 printf("\n%s Files  = %6d  ", Legend[i], S[i][0]);
  380.                 if (ArcSwt) printf("%sed Files = %6d %s Matches = %4d",
  381.                                    Legend[i], S[i][1], Legend[i],
  382.                                    S[i][2]);
  383.                 }
  384.             }
  385.         printf("\n");
  386.         }
  387.  
  388. #ifdef PROF
  389.     t_exit(0);
  390.     t_report(0);
  391.     t_stop();
  392. #endif
  393.     }
  394.  
  395. /*----------------------------------------------------------------------*/
  396. /* WalkTree is a recursive routine that walks the directory structure    */
  397. /* specifed by the external T_Path.  It bypasses Volume IDs and builds    */
  398. /* a linked list queue of directories that is processed after all of    */
  399. /* the file entries have been processed.                                */
  400.  
  401.  void
  402. WalkTree (QUE_DEF *Q) {
  403.     extern int      VerboseSwt, CaseSwt, Spaced;
  404.     extern struct Archives Arcs[6];
  405.  
  406.     int             Status, i;
  407.     char            Reply;
  408.     QUE_DEF         Direc;
  409.     QUE_ENTRY      *t, *u;
  410.     char           *p;
  411.     struct DIR_ENTRY  DirBlk;        /* Directory Entry structure            */
  412.     DOS_FILE_TIME   Time;
  413.     DOS_FILE_DATE   Date;
  414.  
  415.     InitQueue(&Direc);
  416.     strcat(T_Path, "*.*");
  417. #ifdef PROF
  418.     t_entry(2);
  419. #endif
  420.     Status = FIND_FIRST(T_Path, &DirBlk, 0xFF);
  421. #ifdef PROF
  422.     t_exit(2);
  423. #endif
  424.     *(strrchr(T_Path, '\\') + 1) = '\0';
  425.     while (!Status) {
  426.  
  427.         if (kbhit()) {
  428.             Reply = getch();
  429.             if (Reply == 0x1B) {
  430.                 fprintf(stderr, "    FFF terminated by user request.\n");
  431.                 exit(1);
  432.                 }
  433.             }
  434.  
  435.         if ((DirBlk.D_ATTRIB & A_VOLID) != 0) {    /* Bypass Volume Label        */
  436. #ifdef PROF
  437.             t_entry(2);
  438. #endif
  439.             Status = FIND_NEXT(&DirBlk);
  440. #ifdef PROF
  441.             t_exit(2);
  442. #endif
  443.             continue;
  444.             }
  445.         if ((DirBlk.D_ATTRIB & A_DIREC) != 0) {    /* Process subdirectory        */
  446.             if (DirBlk.D_NAME[0] != '.') {
  447.                 Enque(&Direc, DirBlk.D_NAME);
  448.                 }
  449.             }
  450.         else {                                    /* Process file entry        */
  451.             ++TotalFiles;
  452.             if ( SearchQ(DirBlk.D_NAME) ) {
  453.                 ++TotalMatch;
  454.                 if (PageSwt) ChkPage();
  455.                 strcpy(V_Name, DirBlk.D_NAME);
  456.                 strcpy(V_Path, T_Path);
  457.                 if (CaseSwt == ON) {
  458.                     strlwr(V_Name);
  459.                     strlwr(V_Path);
  460.                     }
  461.                 if (VerboseSwt) {
  462.                     fputs("  ", stdout);
  463.                     Time.u = DirBlk.D_TIME;
  464.                     Date.u = DirBlk.D_DATE;
  465.                     PrtVerbose(V_Path, V_Name, &Time, &Date,
  466.                                DirBlk.D_SIZE);
  467.                     }
  468.                 else {
  469.                     fputs(V_Path, stdout);
  470.                     puts(V_Name);
  471.                     }
  472.                 ++Lnno;
  473.                 Spaced = 0;
  474.                 }
  475.  
  476. /* Check the file name for the various archive identifying extensions        */
  477.  
  478.             if ((p = strchr(DirBlk.D_NAME, '.')) != NULL) {
  479.                 for (i = 0; Arcs[i].Ext[0] != '\0' && stricmp(p + 1, Arcs[i].Ext); ++i);
  480.                 ArcType = Arcs[i].Type;
  481.                 switch (ArcType) {
  482.                     case arc:
  483.                     case pak:
  484.                         ++S[ArcType][0];
  485.                         if (ArcSwt) {
  486.                             strcat(T_Path, DirBlk.D_NAME);
  487.                             DoArc(T_Path);
  488.                             *(strrchr(T_Path, '\\') + 1) = '\0';
  489.                             }
  490.                         break;
  491.                     case zip:
  492. #ifdef PROF
  493.                         t_entry(4);
  494. #endif
  495.                         ++S[ArcType][0];
  496.                         if (ArcSwt) {
  497.                             strcat(T_Path, DirBlk.D_NAME);
  498.                             DoZip(T_Path);
  499.                             *(strrchr(T_Path, '\\') + 1) = '\0';
  500.                             }
  501. #ifdef PROF
  502.                         t_exit(4);
  503. #endif
  504.                         break;
  505.                     case zoo:
  506.                         ++S[ArcType][0];
  507.                         if (ArcSwt) {
  508.                             strcat(T_Path, DirBlk.D_NAME);
  509.                             DoZOO(T_Path);
  510.                             *(strrchr(T_Path, '\\') + 1) = '\0';
  511.                             }
  512.                         break;
  513.                     case lzh:
  514.                         ++S[ArcType][0];
  515.                         if (ArcSwt) {
  516.                             strcat(T_Path, DirBlk.D_NAME);
  517.                             DoLzh(T_Path);
  518.                             *(strrchr(T_Path, '\\') + 1) = '\0';
  519.                             }
  520.                         break;
  521.                     }
  522.                 }
  523.             }
  524. #ifdef PROF
  525.         t_entry(2);
  526. #endif
  527.         Status = FIND_NEXT(&DirBlk);
  528. #ifdef PROF
  529.         t_exit(2);
  530. #endif
  531.         }
  532.     p = strrchr(T_Path, '\\') + 1;
  533.  
  534. /* Process any entries in the linked list of subdirectories                    */
  535.  
  536.     for (t = Direc.Head; t != NULL;) {
  537.         *p = '\0';
  538.         strcat(T_Path, t->Body);
  539.         strcat(T_Path, "\\");
  540.         WalkTree(Q);
  541.         u = t->Next;
  542.         free(t->Body);
  543.         free(t);
  544.         t = u;
  545.         }
  546.     }
  547.  
  548. /*----------------------------------------------------------------------*/
  549.  
  550. /*----------------------------------------------------------------------*/
  551. /* SearchQ takes a file name as input and matches it against all of the    */
  552. /* patterns in the linked list of patterns built from command line        */
  553. /* arguments.  The pattern list is an external.                            */
  554.  
  555.  int
  556. SearchQ (char *Str) {
  557.     extern QUE_DEF    PatQue;
  558.     QUE_ENTRY      *t;
  559.     int             Result;
  560.  
  561.     for (t = PatQue.Head; t != NULL; t = t->Next) {
  562.         Result = Match(Str, t->Body);
  563.         if (Result != 0) return(Result);
  564.         }
  565.     return (0);
  566.     }
  567.  
  568. /*----------------------------------------------------------------------*/
  569. /* ErrorExit is a general routine used to print an error message and    */
  570. /* exit the program.                                                    */
  571.  
  572.  void
  573. ErrorExit (char *Format, ...) {
  574.     va_list         ArgPtr;
  575.     extern char     ProgName[];
  576.  
  577.     fprintf(stderr, "%s: ", ProgName);
  578.     va_start(ArgPtr, Format);
  579.     vfprintf(stderr, Format, ArgPtr);
  580.     va_end(ArgPtr);
  581.     if (errno) perror("    ");
  582.     fprintf(stderr, "\n");
  583.     exit(1);
  584.     }
  585.  
  586. /*----------------------------------------------------------------------*/
  587. /* GetProgName interprets argv[0] to find the program name for error    */
  588. /* messages.  It does NOT work for versions of MS-DOS prior to 3.0.        */
  589.  
  590.  void
  591. GetProgName (char *Name, char *argv) {
  592.     char           *p, *p1;
  593.  
  594.     if ( (p = strrchr(argv, '\\')) != NULL ) ++p;
  595.     else p = argv;
  596.     if ( (p1 = strchr(p, '.')) != NULL ) *p1 = '\0';
  597.     strcpy(Name, p);
  598.     }
  599.  
  600. /*----------------------------------------------------------------------*/
  601. /* PrtVerbose displays the "verbose" line for matched files.  It         */
  602. /* displays the file size (in bytes), file date, and file time as well    */
  603. /* the file name.  By default, it shows the month is 3-character alpha    */
  604. /* form.                                                                */
  605.  
  606.  void
  607. PrtVerbose (char *Path, char *Name, DOS_FILE_TIME * Time, DOS_FILE_DATE * Date,
  608.            long Size) {
  609.     extern int      DateSwt, UsDateSwt;
  610.     extern int        CaseSwt;
  611.  
  612.     static char    *MonTab[] = {
  613.         "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
  614.         "Oct", "Nov", "Dec"
  615.         };
  616.  
  617.     strcpy(V_Name, Name);
  618.     if (CaseSwt == ON) strlwr(V_Name);
  619.     strcpy(V_Path, Path);
  620.     if (CaseSwt == ON) strlwr(V_Path);
  621.     if (DateSwt) {
  622.         printf("%-13s   %02d-%02d-%02d   %02u:%02u %8ld   %s\n", V_Name,
  623.                Date->b.Year + 80, Date->b.Month, Date->b.Day, Time->b.Hour,
  624.                Time->b.Minute, Size, V_Path);
  625.         }
  626.     else if (UsDateSwt) {
  627.         printf("%-13s   %02d/%02d/%02d   %02u:%02u %8ld   %s\n", V_Name,
  628.                Date->b.Month, Date->b.Day, Date->b.Year + 80, Time->b.Hour,
  629.                Time->b.Minute, Size, V_Path);
  630.         }
  631.     else {
  632.         printf("%-13s   %02u %s %02u   %02u:%02u %8ld   %s\n", V_Name, Date->b.Day,
  633.                MonTab[Date->b.Month - 1], Date->b.Year + 80, Time->b.Hour,
  634.                Time->b.Minute, Size, V_Path);
  635.         }
  636.     }
  637.  
  638. /*----------------------------------------------------------------------*/
  639. /* Usage is a pretty conventional routine to display a brief "help"        */
  640. /* message if the program is evoked with no command line arguments        */
  641.  
  642.  void
  643. Usage (void) {
  644.     fprintf(stderr, "USAGE: %s [device(s):[path]pattern [options]\n", ProgName);
  645.     fprintf(stderr, "\nOptions:\n\n");
  646.     fprintf(stderr, "    -a Suppress searching inside of archive files.\n");
  647.     fprintf(stderr, "    -v Display Date/Time and File Size as well as name\n");
  648.     fprintf(stderr, "       and path for all matched files.\n");
  649.     fprintf(stderr, "    -f Modify the date in the Verbose output for sorting\n");
  650.     fprintf(stderr, "       YY/MM/DD form\n");
  651.     fprintf(stderr, "    -u Modify the date in the Verbose output to US normal\n");
  652.     fprintf(stderr, "       form - MM/DD/YY\n");
  653.     fprintf(stderr, "    -p Paginate output every 23 lines\n");
  654.     fprintf(stderr, "    -q Supress the printing of the statistics on files\n");
  655.     fprintf(stderr, "       searched and matched\n");
  656.     fprintf(stderr, "    -c Output in lower case instead of upper case\n\n");
  657.     fprintf(stderr, "    Press \"ESC\" at any time to terminate the search.\n");
  658.     exit(1);
  659.     }
  660.  
  661.  
  662. /*----------------------------------------------------------------------*/
  663. /* ChkPage is used if "paging" is specified on the command line or in    */
  664. /* the Environment Variable.  It pauses the program for user input        */
  665. /* 23 lines to prevent the scrolling entries off the screen before the    */
  666. /* user has read them.                                                    */
  667.  
  668.  void
  669. ChkPage (void) {
  670.     int             Reply;
  671.  
  672.     if (Lnno >= 24) {
  673.         clreol();
  674.         printf("More?...");
  675.         Reply = tolower(getche());
  676.         if ((Reply == 'n') || (Reply == 0x03)) exit(1);
  677.         printf("\r");
  678.         clreol();
  679.         Lnno = 1;
  680.         }
  681.     }
  682.  
  683. /*----------------------------------------------------------------------*/
  684. /* clreol() is used in the ChkPage() routine to clear the "More..."        */
  685. /* message. Turbo C has clreol() in the runtime library but Microsoft    */
  686. /* C doesn't.  This is a very "brute force" method but it is NOT a very    */
  687. /* important function.                                                    */
  688.  
  689. #ifndef __TURBOC__
  690.  
  691.  void
  692. clreol (void) {
  693.     puts("\r                                                                   \r");
  694.     }
  695.  
  696. #endif
  697. /* */
  698.